/**
 * 字牌数据管理器
 * Created by duwei on 2019/2/13.
 */
var ZiPaiEvent = {
    UpPlayerPos: 'UpPlayerPos',//玩家变化
    PlayersStatus: 'PlayersStatus',//玩家准备状态
    UserDisconnect: 'UserDisconnect',//玩家在线状态
    StatusChange: 'StatusChange',//状态变更
    GameStart: 'GameStart',//游戏开始
    GameStartAnimation: 'GameStartAnimation',//开局动画
    CardDeal: 'CardDeal',//发牌
    UpOtherCards: "UpOtherCards",//更新其他玩家手牌
    ResetCards: 'ResetCards',//刷新手牌
    BroadCast: 'BroadCast',//操作广播
    TurnOut: 'TurnOut',//该谁出牌了
    TurnIn: 'TurnIn',//是否进牌
    TishiList: 'TishiList',//听牌提示
    TingCards: 'TingCards',//胡牌提示
    GameOver: 'GameOver',//游戏结算
    JushouStatus: 'JushouStatus',//举手状态
    Baojing: 'Baojing',//报警
    QiePai: 'QiePai',//切牌
    RoomResult: 'RoomResult',//总结算
    QuickStart: 'QuickStart',//快速开始
//================java===================
    onTurnRow: 'onTurnRow',//操作人
    onMoCard: 'onMoCard',//摸牌
    onChuCard: 'onChuCard',//出牌
    chiPengCardDeal: 'chiPengCardDeal',//吃碰后设置牌
    onChiPengGangHu: 'onChiPengGangHu',//吃碰杠胡
    showChiPengGangHu: 'showChiPengGangHu',//显示吃碰杠胡动画
    onCardAscription: 'onCardAscription',//牌归谁
    showGameResult: 'showGameResult',//小结算
    showSelectPiao: 'showSelectPiao',//显示选票
    onSelectedPiao: 'onSelectedPiao',//选票
    onShowSishou: 'onShowSishou',
    opId: 0,//吃碰胡对应的进牌id
};
/**
 * 做全局数据使用，只有牌局内有用
 * @type {{}}
 */
var ZiPaiRoomData = {
    mapId: 0,
    mapName: '',
    roomId: 0,
    players: [],
    isReplay: false,
    playerNum: 3,
    options: {},
    hz_sortId: 2,//牌默认排序方式
    ShouxingID: 0,//首醒ID
    CurRound: 1,
    ZongRound: 8,
};
var ZiPaiManager = cc.Component.extend({
    roomDate: null,
    roomReplayDate: null,
    roomDataType: ROOM_DATA_TYPE.CREATE,
    isReplay: false,
    isReconnect: false,
    isGameStart: false,
    isAllPiao:true,
    MapId: 0,
    ClubId: 0,
    Option: {},
    Owner: 0,
    RoomID: 0,
    CurRound: 1,
    ZongRound: 8,
    WanfaDesp: '',
    PlayersNum: 3,
    PlayerInfos: [],
    PlayerMap: {},
    ReconnectPlayers: [],
    g_pos_to_uid: {},
    g_uid_to_pos: {},
    g_uid_to_sex: {},
    g_uid_to_ready: {},
    g_uid_to_offline: {},
    g_uid_to_AcCards: {},
    g_pos_to_info: {},
    g_uid_to_info: {},
    g_uid_to_InGameScore: [],
    g_uid_to_Score: {},
    g_uid_to_DiscardCards: {},//弃牌
    g_uid_to_ChuCards: {},//出牌
    g_uid_to_Menzi: {},//吃碰牌
    g_uid_to_Notice: {},
    g_uid_to_Freeze: {},//冻结牌
    g_uid_to_Hands: {},//手牌
    g_uid_to_ChiList: {},
    g_uid_to_LastTurnInFlag: {},
    g_uid_to_Piao: {},//飘
    g_uid_to_opencards: [],//对应的亮牌
    isShowReadyBtn: false,//显示准备按钮
    PlayersStatus: {},//玩家准备状态
    GameStatus: 0,//房间状态
    SecondStart: false,//第一句已经打完
    BankerUserID: 0,//庄家UID
    BroadCastData: {},//广播数据
    SeverCardList: [],//当前手牌（服务器数据）
    CardList: [],//客户端计算后手牌
    Handshuxi: 0,//自己的胡息数
    RoundInfo: null,//回合信息
    LeftCardCount: 80,//剩余牌数
    isDaiKan: true,//是否带坎
    debuglog: function () {
        if (!cc.sys.isNative) {
            cc.log(arguments[0]);
        }
    },
    addListener: function (code, listener) {
        if (this.isReplay) {
            if (code == P.GS_GameStart //109 开始游戏，之后发牌
                || code == P.GS_CardDeal //107 发牌
                || code == P.GS_GameTurn_In//111 请客户端选择是否进牌
                || code == P.GS_GameOver//105 服务器宣布游戏结束
                || code == P.GS_BroadcastAction//112 广播
            ) {
                eventManager.addListener(code, listener, this);
            }
        } else {
            network.addListener(code, listener, this);
        }
    },
    onExit: function () {
        this.debuglog('ZiPaiManager   onExit');
        eventManager.removeListeners(this);
        network.removeListenersForTarget(this);
    },
    initListener: function () {
        /**
         * 客户端状态变更
         * code 11
         */
        this.addListener(P.GS_StatusChange, this.onStatusChange.bind(this));
        /**
         * 开始游戏，之后发牌
         * code 109
         */
        this.addListener(P.GS_GameStart, this.onGameStart.bind(this));
        /**
         * 发牌
         * code 107
         */
        this.addListener(P.GS_CardDeal, this.onCardDeal.bind(this));
        /**
         * 玩家加入，离开
         * code 101
         */
        this.addListener(P.GS_UserJoin, this.onUserJoin.bind(this));
        /**
         * 玩家临时掉线
         * code 103
         */
        this.addListener(P.GS_UserDisconnect, this.onUserDisconnect.bind(this));
        /**
         * 房间内断开重连
         * code 1
         */
        this.addListener(P.GS_Login, this.onRoleLoginOK.bind(this));
        /**
         * 离开房间
         * code 102
         */
        this.addListener(P.GS_UserLeave, this.onLeaveOK.bind(this));
        /**
         * 到谁出牌了，开始读秒
         * code 110
         */
        this.addListener(P.GS_GameTurn_Out, this.onTurnOut.bind(this));
        /**
         * 请客户端选择是否进牌
         * code 111
         */
        this.addListener(P.GS_GameTurn_In, this.onTurnIn.bind(this));
        /**
         * 广播
         * code 112
         */
        this.addListener(P.GS_BroadcastAction, this.onBroadCast.bind(this));
        /**
         * 服务器宣布游戏结束
         * code 105
         */
        this.addListener(P.GS_GameOver, this.onGameOver.bind(this));
        /**
         * 投票广播
         * code 116
         */
        this.addListener(P.GS_Vote, this.onGameVote.bind(this));
        /**
         * 跑马灯
         * code 117
         */
        this.addListener(P.GS_Marquee, this.onMaDeng.bind(this));
        /**
         * 房间结算
         * code 118
         */
        this.addListener(P.GS_RoomResult, this.onRoomResult.bind(this));
        /**
         * 号被顶
         * code 119
         */
        this.addListener(P.GS_UserKick, this.onUserKick.bind(this));
        /**
         * 广播每个人抓鸟，大鸟状态
         * code 120
         */
        this.addListener(P.GS_Niao_Status, this.onNiaoStatus.bind(this));
        /**
         * 广播三个玩家的举手状态，在每一轮开始的时候广播
         * code 122
         */
        this.addListener(P.GS_Jushou_Status, this.onJushouStatus.bind(this));
        /**
         * 请客户端断开连接，关闭定时器，重连等
         * code 121
         */
        this.addListener(P.GS_Pls_Disconnect, this.onPlsDisconnect.bind(this));
        /**
         * 广播4个玩家的报警状态
         * code 123
         */
        this.addListener(P.GS_Baojing_Status, this.onBaojing.bind(this));
        /**
         * 广播4个玩家的翻醒状态
         * code 124
         */
        this.addListener(P.GS_Fanxing_Status, this.onFanXing.bind(this));
        /**
         * 等待玩家选王调
         * code 125
         */
        this.addListener(P.GS_Wangdiao_status, this.onWangdiao.bind(this));
        /**
         * 提示听牌列表
         * code 99
         */
        this.addListener(P.GS_TingPai_List, this.setTingPaiList.bind(this));
        /**
         * 提示牌列表
         * code 98
         */
        this.addListener(P.GS_TishiPai_List, this.setTishiList.bind(this));
        /**
         * 手动准备
         * code 126
         */
        this.addListener(P.GS_ReadyStatus, this.setPlayersStatus.bind(this));
        /**
         * 切牌
         * code 128
         */
        this.addListener(P.GS_Qiepai, this.onQiepai.bind(this));
        /**
         * 快速开局
         * code 129
         */
        this.addListener(P.GS_QuickStart_Status, this.onQuickStart.bind(this));
        this.addListener(P.GS_QuickStartGame, this.onQuickStartGame.bind(this));
        /**
         * 网络连接断开
         * code 10001
         */
        this.addListener(P.GS_NetWorkClose, this.NetWorkCloseFunc.bind(this));
        /**
         * home事件
         */
        eventManager.addListener(cc.game.EVENT_HIDE, this.Game_On_Hide.bind(this), this);
        //eventManager.addListener(cc.game.EVENT_SHOW, this.Game_On_Show.bind(this), this);
    },
    /**
     * 玩家切后台离线
     * @constructor
     */
    Game_On_Hide: function () {
        if (this.OffCancelReady) {
            network.sendPhz(5000, 'Ready/0');
        }
    },
    getPlayerNum: function () {
        if (this.Option['maxPlayerCnt']) {
            return this.Option['maxPlayerCnt'];
        }
        if (this.Option['PlayerCount']) {
            return this.Option['PlayerCount'];
        }
        if (this.WanfaDesp.indexOf('两人玩') >= 0) {
            return 2;
        }
        if (this.WanfaDesp.indexOf('三人玩') >= 0) {
            return 3;
        }
        if (this.WanfaDesp.indexOf('四人玩') >= 0) {
            return 4;
        }
        if (this.Option['sanrenwan']) {
            return 3;
        }
        if (this.Option['erren']) {
            return 2;
        }
        return 3;
    },
    /**
     * 设置全局数据
     */
    setZiPaiRoomData: function () {
        /**
         * 房间用
         */
        ZiPaiRoomData.mapId = this.MapId || 0;
        ZiPaiRoomData.mapName = '';
        ZiPaiRoomData.roomId = this.RoomID || 0;
        ZiPaiRoomData.players = this.PlayerInfos || [];
        ZiPaiRoomData.isReplay = this.isReplay;
        ZiPaiRoomData.playerNum = this.PlayersNum || 3;
        ZiPaiRoomData.options = this.Option || {};
        ZiPaiRoomData.ShouxingID = this.ShouxingID;
        /**
         * 全局用
         */
        gameData.distance = "200";
        gameData.wanfatype = 'go';
        gameData.roomId = this.RoomID;
        gameData.wanfaDesp = this.WanfaDesp;
        gameData.curRound = this.CurRound || 1;
        gameData.totalRound = this.ZongRound;
        gameData.players = this.PlayerInfos;
        gameData.playerNum = this.PlayersNum;
        gameData.roomClubId = this.ClubId;
        gameData.ownerUid = this.Owner;
        gameData.options = this.Option || {};
    },
    /**
     * 设置玩法配置
     */
    setWanFaConfig: function () {

    },
    /**
     * 设置玩法字段，用于玩法解析
     */
    setOption: function () {
        this.debuglog('setOption');
        this.debuglog(this.Option);
        this.MapId = this.Option['mapid'];
        this.ClubId = this.Option['club_id'] || 0;
        this.ZongRound = this.Option['rounds']||this.Option['jushu'];
        this.WanfaDesp = this.Option['desp'];
        this.Sipai = this.Option['sipai'];//死牌
        this.Sipaicnt = this.Option['sipaicnt'] || 20;//死牌数
        this.Fanxing = this.Option['Fanxing'];//翻醒
        this.QuickChi = this.Option['QuickChi'];//快捷吃牌
        this.QuickStart = this.Option['QuickStart'];//快速开局
        this.OffCancelReady = this.Option['OffCancelReady'];//离线取消准备
        this.withPiao = this.Option['withPiao'];//带飘
        this.setWanFaConfig();
    },
    initRoomDate: function (data) {
        if (this.isReplay) {
            this.roomDate = data[0]['data'];
            this.roomReplayDate = new ReplayData(data);
            this.setCurRound(parseInt(gameData.recordIds[1]));
        } else {
            this.roomDate = data;
        }
        this.debuglog(this.roomDate);
        this.Option = JSON.parse(this.roomDate['Option']);
        this.setOption();
        this.Owner = this.roomDate['Owner'];
        this.RoomID = this.roomDate['RoomID'];
        if (!this.isReconnect) {
            this.onUserJoin(this.roomDate);
        } else {//重连数据处理
            this.ReconnectPlayers = this.roomDate['Players'];
            this.PlayerInfos = [];
            for (var i = 0; i < this.ReconnectPlayers.length; i++) {
                var reconnectPlayerDate = this.ReconnectPlayers[i];
                var userInfo = reconnectPlayerDate['User'];
                var cardInfo = reconnectPlayerDate['Card'];
                var userID = reconnectPlayerDate['UserID'];
                this.g_uid_to_AcCards[userID] = reconnectPlayerDate['LastAcCards'];
                this.g_uid_to_offline[userID] = !!reconnectPlayerDate['Offline'];
                this.g_uid_to_InGameScore[userID] = reconnectPlayerDate['InGameScore'];
                this.g_uid_to_Score[userID] = reconnectPlayerDate['Score'];
                this.g_uid_to_ChiList[userID] = reconnectPlayerDate['ChiList'];
                this.g_uid_to_LastTurnInFlag[userID] = reconnectPlayerDate['LastTurnInFlag'];

                this.g_uid_to_Hands[userID] = cardInfo['Hands'];
                this.g_uid_to_DiscardCards[userID] = cardInfo['DiscardCards'];
                this.g_uid_to_Menzi[userID] = cardInfo['Menzi'];
                this.g_uid_to_Notice[userID] = cardInfo['Notice'];
                this.g_uid_to_Freeze[userID] = cardInfo['Freeze'];
                if (userID == gameData.uid) {
                    this.ChiList = reconnectPlayerDate['ChiList'];
                    this.setChiArray();
                    this.setSeverCardList(cardInfo['Hands'], 'Reconnect');
                    this.setCardList();
                }
                //定位
                if (userInfo.GPS && userInfo.GPS.length > 0) {
                    try {
                        var GPS = JSON.parse(userInfo.GPS);
                        userInfo.locCN = GPS.locationInfo;
                        userInfo.loc = GPS.location;
                        userInfo.isOpenLocation = GPS.isOpenLocation;
                    } catch (e) {
                        userInfo.locCN = '未开启地理位置共享';
                        userInfo.loc = 'false';
                        userInfo.isOpenLocation = 0;
                    }
                } else {
                    userInfo.locCN = '未开启地理位置共享';
                    userInfo.loc = 'false';
                    userInfo.isOpenLocation = 0;
                }
                this.PlayerInfos.push(userInfo);
            }
            this.ShouxingID = this.roomDate['ShouxingID'];
            this.BankerUserID = this.roomDate['BankerUserID'];
            this.GameStatus = this.roomDate['GameStatus'];
            this.setLeftCardCount(this.roomDate['LeftCardCount']);
            this.setCurRound(this.roomDate['GameSeq'] || 1);
            this.RoundInfo = this.roomDate['Round'];
            if (this.PlayerInfos.length >= this.getPlayerNum()) {
                this.isGameStart = (this.roomDate['GameSeq'] > 1) ? true : (this.RoundInfo && this.GameStatus > 0);
            } else {
                this.isGameStart = false;
            }
            if (this.isGameStart) {
                var card = this.RoundInfo['Card'];
                var from = this.RoundInfo['From'];
                var mo = this.RoundInfo['Mo'];//
                var seq = this.RoundInfo['Seq'];//第几轮
                if (card != void 0) {
                    if (card == 0) {
                        this.Turn = from;
                        this.Second = 0;
                        this.TurnOutSeq = seq;
                        this.Freeze = null;
                        this.Notice = null;
                    } else {
                        this.ChiList = this.g_uid_to_ChiList[gameData.uid];
                        this.setChiArray();
                        this.AcCards = this.g_uid_to_AcCards[gameData.uid];
                        this.TurnInCard = card;
                        this.Flag = this.g_uid_to_LastTurnInFlag[gameData.uid];
                        this.Remark = '';
                        this.TurnInSeq = seq;
                        cc.log('Flag==' + this.Flag.toString(16));
                    }
                }
            }
        }
        this.setUpPlayerPos(true);
        this.setZiPaiRoomData();
    },
    setUpPlayerPos: function (isInit) {
        gameData.players = this.PlayerInfos;
        this.PlayersNum = this.getPlayerNum();
        this.PlayerMap = {};
        var pos = 0;
        for (var i = 0; i < this.PlayerInfos.length; i++) {
            this.PlayerMap[this.PlayerInfos[i].ID] = this.PlayerInfos[i];
            if (this.PlayerInfos[i].ID == gameData.uid) {
                pos = i;
            }
        }
        this.pos0 = pos;
        this.pos1 = (pos + 1) % this.PlayersNum;
        this.pos2 = (pos + 2) % this.PlayersNum;
        this.pos3 = (pos + 3) % this.PlayersNum;

        this.g_pos_to_uid = {};
        this.g_uid_to_pos = {};
        this.g_uid_to_sex = {};
        this.g_pos_to_info = {};
        this.g_uid_to_opencards = [];
        for (var i = 0; i < this.PlayersNum; i++) {
            var idx = this['pos' + i];
            var row = i;
            var info = this.PlayerInfos[idx];
            this.g_pos_to_info[row] = info;
            if (info) {
                this.g_pos_to_uid[row] = info.ID;
                this.g_uid_to_pos[info.ID] = row;
                this.g_uid_to_sex[info.ID] = info.Sex || 1;
            }
        }
        if (!isInit) {
            eventManager.dispatchEvent(ZiPaiEvent.UpPlayerPos);
            eventManager.dispatchEvent(EventKey.ClubRoomPlayerStateRefresh);
            eventManager.dispatchEvent(EventKey.ClubPlayerEnterExit, gameData.players);
        }
    },
    clearGameDate: function () {
        this.TingCards = [];
        this.TishiList = [];
        this.g_uid_to_Hands = {};
        this.g_uid_to_DiscardCards = {};
        this.g_uid_to_Menzi = {};
        this.g_uid_to_Notice = {};
        this.g_uid_to_Freeze = {};
    },
    ctor: function (data, roomDataType,room) {
        this._super();
        this.room = room;
        mAction.initGame();
        this.setName('ZiPaiManager');
        this.debuglog('ZiPaiManager');
        network.stop();
        this.roomDataType = roomDataType;
        this.isReplay = (roomDataType == ROOM_DATA_TYPE.REPLAY);
        this.isReconnect = (roomDataType == ROOM_DATA_TYPE.RECONNECT);
        this.initRoomDate(data);
        this.initListener();
    },
    /**
     * 房间内断开重连
     * code 1
     * @param data
     */
    onRoleLoginOK: function (data) {
        this.debuglog('onRoleLoginOK');
        this.debuglog(data);
    },
    /**
     * 设置当前局数
     */
    setCurRound: function (Round) {
        this.CurRound = Round;
        gameData.curRound = this.CurRound;
    },
    /**
     * 客户端状态变更
     * code 11
     * @param data
     */
    onStatusChange: function (data) {
        this.debuglog('onStatusChange');
        this.debuglog(data);
        this.setCurRound(data['Round']);
        eventManager.dispatchEvent(ZiPaiEvent.StatusChange);
    },
    /**
     * 提示牌列表
     * code 98
     * @param data
     */
    setTishiList: function (data) {
        this.debuglog('setTishiList');
        this.debuglog(data);
        this.TingCards = [];
        this.TishiList = data['TingCards'];
        eventManager.dispatchEvent(ZiPaiEvent.TishiList);
    },
    /**
     * 提示听牌列表
     * code 99
     * @param data
     */
    setTingPaiList: function (data) {
        this.debuglog('setTingPaiList');
        this.debuglog(data);
        this.TingCards = data['TingCards'];
        eventManager.dispatchEvent(ZiPaiEvent.TingCards);
    },
    /**
     * 玩家加入
     * code 101
     * @param data
     */
    onUserJoin: function (data) {
        this.debuglog('onUserJoin');
        this.debuglog(data);
        this.OfflineList = data['OfflineList'];
        this.PlayerInfos = data['Users'];
        this.setUpPlayerPos();
    },
    /**
     * 离开房间
     * code 102
     * @param data
     */
    onLeaveOK: function (data) {
        this.debuglog('onLeaveOK');
        this.debuglog(data);
        var self = this;
        var Users = data['Users'];
        var ReasonStr = data['ReasonStr'];
        if (Users[0] == gameData.uid) {
            showAlert(ReasonStr, function () {
                showBoard('HallBoard');
            });
        }
    },
    /**
     * 玩家临时掉线
     * code 103
     * @param data
     */
    onUserDisconnect: function (data) {
        this.debuglog('onUserDisconnect');
        this.debuglog(data);
        var UserID = data['UserID'];
        var ConnectStatus = data['ConnectStatus'];
        var flag = false;
        if (ConnectStatus == 'disconnected') {
            flag = true;
        } else if (ConnectStatus == 'online') {
            flag = false;
        }
        this.g_uid_to_offline[UserID] = flag;
        eventManager.dispatchEvent(ZiPaiEvent.UserDisconnect);
    },
    /**
     * 服务器宣布游戏结束
     * code 105
     * @param data
     */
    onGameOver: function (data) {
        this.debuglog('onGameOver');
        this.debuglog(data);
        this.gameOverData = data;
        var Users = this.gameOverData['Users'];
        for (var i = 0; i < Users.length; i++) {
            var infoData = Users[i];
            var uid = infoData['UserID'];
            var row = this.g_uid_to_pos[uid];
            this.g_uid_to_Hands[uid] = infoData['Hand'];
            this.g_uid_to_DiscardCards[uid] = infoData['AllCards']['DiscardCards'];
            this.g_uid_to_Menzi[uid] = infoData['AllCards']['Menzi'];//吃碰牌
            this.g_uid_to_Notice[uid] = infoData['AllCards']['Notice'];
            this.g_uid_to_Freeze[uid] = infoData['AllCards']['Freeze'];//冻结牌
            this.g_uid_to_Score[uid] = infoData['Score'];
            if (uid != gameData.uid) {
                this['CardList' + row] = mCard.getOtherCardList(infoData['Hand']);
            }
        }
        if (this.gameOverData.Sipai && this.PlayersNum == 2) {
            this['CardList2'] = mCard.getOtherCardList(this.gameOverData.Sipai);
        }
        eventManager.dispatchEvent(ZiPaiEvent.GameOver);
    },
    /**
     * 删除牌数据
     * @param card
     * @param userPos
     * @param outCardColumn
     * @param outCardRow
     */
    removeCardInList: function (card, userPos, outCardColumn, outCardRow) {
        var cardList = userPos == 0 ? this.CardList : this['CardList' + userPos];
        if (cardList == undefined || cardList == null) {
            return;
        }
        if (outCardColumn && outCardRow) {
            for (var i = cardList.length - 1; i >= 0; i--) {
                var cards = cardList[i];
                for (var j = cards.length - 1; j >= 0; j--) {
                    if (i == (outCardColumn - 1) && j == (outCardRow - 1) && card == cards[j]) {
                        cards.splice(j, 1);
                        if (cards.length == 0) {
                            cardList.splice(i, 1);
                        }
                        return;
                    }
                }
            }
        }
        for (var i = cardList.length - 1; i >= 0; i--) {
            var cards = cardList[i];
            for (var j = cards.length - 1; j >= 0; j--) {
                if (cards[j] == card) {
                    cards.splice(j, 1);
                    if (cards.length == 0) {
                        cardList.splice(i, 1);
                    }
                    return;
                }
            }
        }
    },
    /**
     * 删除手牌
     * @param cardsToRemove
     * @param userPos
     * @param outCardColumn
     * @param outCardRow
     */
    removeCards: function (cardsToRemove, userPos, outCardColumn, outCardRow) {
        var cards = userPos == 0 ? this.SeverCardList : this['SeverCardList' + userPos];
        for (var i = 0; i < cardsToRemove.length; i++) {
            var deleteList = [];
            if (cards) {
                for (var j = cards.length - 1; j >= 0; j--) {
                    if (cards[j] == cardsToRemove[i]) {
                        deleteList.push([j]);
                        break;
                    }
                }
            }
            removeInArray(cards, deleteList);
        }
        if (cardsToRemove && cardsToRemove.length == 1 && outCardColumn && outCardRow) {
            this.removeCardInList(cardsToRemove[0], userPos, outCardColumn, outCardRow);
        } else {
            for (var i = 0; i < cardsToRemove.length; i++) {
                this.removeCardInList(cardsToRemove[i], userPos);
            }
        }
    },
    /**
     * 添加牌
     * @param cardToAdd
     */
    addCard: function (cardToAdd) {
        this.SeverCardList.push(cardToAdd);
        this.SeverCardList.sort(function (a, b) {
            return a - b;
        });
        this.CardList = mCard.getCardList(this.SeverCardList);
        // var isAdd = false;
        // for (var i = 0; i < this.CardList.length; i++) {
        //     var cards = this.CardList[i];
        //     if ((cards.length == 1 && cards[0] == cardToAdd) || (cards.length == 2 && cards[0] == cardToAdd && cards[1] == cardToAdd)) {
        //         cards.push(cardToAdd);
        //         isAdd = true;
        //         break;
        //     }
        // }
        // if (isAdd == false) {
        //     this.CardList.push([cardToAdd]);
        // }
        this.Handshuxi = mCard.getHandsHuXi(deepCopy(this.CardList));
        //eventManager.dispatchEvent(ZiPaiEvent.CardDeal);
    },
    /**
     * 添加王牌牌
     */
    addCard21: function () {
        var tmpCardList = deepCopy(this.CardList);
        var tmpCardListLen = tmpCardList.length;
        var tmpCommbo = [];
        var tmpStArr = [];
        
        for (var i = 0; i < tmpCardListLen; i++){
            tmpCommbo = deepCopy(tmpCardList[i]);
            tmpCommbo.sort(function (a, b) {
                return a - b;
            });
            if (tmpCommbo.length == 2) {
                var type = 100;
                if (tmpCommbo[0] == tmpCommbo[1]) {
                    if (tmpCommbo[0] > 10) type = 1;
                    else type = 2;
                } else if ((tmpCommbo[0] == 11 && tmpCommbo[1] == 12) || (tmpCommbo[0] == 11 && tmpCommbo[1] == 13) ||
                    (tmpCommbo[0] == 12 && tmpCommbo[1] == 13)) {
                    type = 3;
                } else if ((tmpCommbo[0] == 1 && tmpCommbo[1] == 2) || (tmpCommbo[0] == 1 && tmpCommbo[1] == 3) ||
                    (tmpCommbo[0] == 2 && tmpCommbo[1] == 3)) {
                    type = 4;
                } else if ((tmpCommbo[0] == 12 && tmpCommbo[1] == 17) || (tmpCommbo[0] == 12 && tmpCommbo[1] == 20) ||
                    (tmpCommbo[0] == 17 && tmpCommbo[1] == 20)) {
                    type = 5;
                } else if ((tmpCommbo[0] == 2 && tmpCommbo[1] == 7) || (tmpCommbo[0] == 2 && tmpCommbo[1] == 10) ||
                    (tmpCommbo[0] == 7 && tmpCommbo[1] == 10)) {
                    type = 6;
                } else if (tmpCommbo[0] + 10 == tmpCommbo[1] && tmpCommbo[1] != 21) {
                    type = 7;
                } else if (tmpCommbo[0] > 10 && tmpCommbo[0] < 21 && tmpCommbo[1] > 10 && tmpCommbo[1] < 21 &&
                    (tmpCommbo[0] + 1 == tmpCommbo[1] || tmpCommbo[0] + 2 == tmpCommbo[1])) {
                    type = 8;
                } else if (tmpCommbo[0] > 0 && tmpCommbo[0] < 11 && tmpCommbo[1] > 1 && tmpCommbo[1] < 11 &&
                    (tmpCommbo[0] + 1 == tmpCommbo[1] || tmpCommbo[0] + 2 == tmpCommbo[1])) {
                    type = 8;
                } else {
                    type = 100;
                }
                var tmpVal = [type, i];
                tmpStArr.push(tmpVal);
            }
        }

        tmpStArr.sort(function (a, b) {
            return a[0] - b[0];
        });

        //
        if (tmpStArr && tmpStArr[0] && tmpStArr[0][0] != 100){
            tmpCardList[tmpStArr[0][1]].push(21);
            this.CardList = tmpCardList;
            this.SeverCardList.push(21);
            return;
        }
        
        //从列表的最后插如数据
        /*
        if (tmpCardListLen < zipai.curBaipaiLength) {
            tmpCardList.push([21]);
            this.SeverCardList.push(21);
        }
        else {
         */
            var isInsert = false;
            for (var i = tmpCardListLen - 1; i > -1; i--) {
                if (tmpCardList[i].length < 3) {
                    tmpCardList[i].push(21);
                    this.SeverCardList.push(21);
                    isInsert = true;
                    break;
                }
            }

            if (isInsert == false) {
                tmpCardList.push([21]);
                this.SeverCardList.push(21);
            }
        //}
        this.CardList = tmpCardList;
        //this.Handshuxi = mCard.getHandsHuXi(deepCopy(this.CardList));
    },
    /**
     * 回放亮张设置数据
     * @param card
     * @param userPos
     */
    showReplayLZCard: function (card, userPos) {
        //提过的亮张不要放进手牌  计算手里的牌数量
        var addLiangZhangCard = false;
        var cards = (userPos == 0) ? this.SeverCardList : this['SeverCardList' + userPos];
        var comboList = mAction.combos[userPos];
        var comboNum = 0;
        for (var s = 0; s < comboList.length; s++) {
            comboNum = comboNum + comboList[s].cards.length;
        }
        if (cards && (cards.length + comboNum) != 21) {
            addLiangZhangCard = true;
        }
        if (userPos == 0) {
            if (addLiangZhangCard)
                this.SeverCardList.push(card);
            this.CardList = mCard.getCardList(this.SeverCardList);
        } else {
            if (addLiangZhangCard)
                this['SeverCardList' + userPos].push(card);
            this['CardList' + userPos] = mCard.getOtherCardList(this['SeverCardList' + userPos]);
        }
    },
    setSeverCardList: function (Cards, type) {
        this.debuglog("当前=" + this.SeverCardList);
        this.debuglog(type + "=" + Cards);
        if (this.SeverCardList) {
            this.debuglog("长度=" + this.SeverCardList.length + "===" + Cards.length);
        }
        this.SeverCardList = Cards;
    },
    getSeverCardList: function () {
        return this.SeverCardList;
    },
    /**
     * 设置剩余牌数
     * @param count
     * @param type
     */
    setLeftCardCount: function (count, type) {
        if (cc.isNumber(count)) {
            this.LeftCardCount = count;
            mAction.leftCardCount = this.LeftCardCount;
        }
    },
    /**
     * 发牌
     * code 107
     * @param data
     */
    onCardDeal: function (data) {
        this.debuglog('onCardDeal');
        this.debuglog(data);
        var uid = data['ToUser'];
        var pos = this.g_uid_to_pos[uid];
        if (pos == 0) {
            this.setLeftCardCount(data['LeftCard'], 'onCardDeal');
            this.setSeverCardList(data['Cards']);
            this.setCardList();
            eventManager.dispatchEvent(ZiPaiEvent.CardDeal);
        } else {
            this.setOtherCardList(data['Cards'], pos);
            eventManager.dispatchEvent(ZiPaiEvent.UpOtherCards, pos);
        }
    },
    /**
     * 其他玩家手牌信息
     * @param Cards
     * @param pos
     */
    setOtherCardList: function (Cards, pos) {
        this['SeverCardList' + pos] = Cards;
        this['CardList' + pos] = mCard.getOtherCardList(Cards);
    },
    /**
     * 其他玩家手牌信息(摸到王)
     * @param Cards
     * @param pos
     */
    setOtherCardListBy21: function (pos) {
        this['SeverCardList' + pos].push(21);
        this['CardList' + pos] = mCard.getOtherCardList(this['SeverCardList' + pos]);
    },
    /**
     * 设置手牌
     */
    setCardList: function () {
        this.CardList = mCard.getCardList(this.SeverCardList);
    },
    /**
     * 设置手牌(吃碰跑啸倾)
     */
    setCardListByDel: function (targetCardId, op) {
        //this.CardList = mCard.getCardList(this.SeverCardList);
        this.CardList = mCard.getCardListByDel(this.CardList, this.SeverCardList, targetCardId, op);
    },
    /**
     * 刷新手牌
     */
    resetCards: function () {
        this.setCardList();
        eventManager.dispatchEvent(ZiPaiEvent.ResetCards);
    },
    getHandshuxi: function () {
        if (gameData.mapId == app.map_id.QYLDS || gameData.mapId == app.map_id.YZCHZ){
            this.Handshuxi = 0;
        }
        else {
            this.Handshuxi = mCard.getHandsHuXi(deepCopy(this.CardList));
        }
        return this.Handshuxi;
    },
    /**
     * 开始游戏，之后发牌
     * code 109
     * @param data
     */
    onGameStart: function (data) {
        this.debuglog('onGameStart');
        this.debuglog(data);
        this.isGameStart = true;
        this.BankerUserID = data['BankerUserID'];
        this.clearGameDate();
        eventManager.dispatchEvent(ZiPaiEvent.GameStart);
        eventManager.dispatchEvent(EventKey.ClubRoomGameStart);
    },
    /**
     * 比较两个数组差异
     * @param arr1
     * @param arr2
     * @returns {Array}
     */
    getArrayDifference: function (arr1, arr2) {
        var obj1 = {};
        for (var i = 0; i < arr1.length; i++) {
            var key1 = arr1[i];
            if (!obj1.hasOwnProperty(key1)) {
                obj1[key1] = 0;
            }
            obj1[key1]++;
        }
        var obj2 = {};
        for (var j = 0; j < arr2.length; j++) {
            var key2 = arr2[j];
            if (!obj2.hasOwnProperty(key2)) {
                obj2[key2] = 0;
            }
            obj2[key2]++;
        }
        var diff_arr = [];
        var min_obj = deepCopy(Object.keys(obj1) < Object.keys(obj2) ? obj1 : obj2);
        for (var k in min_obj) {
            if (min_obj.hasOwnProperty(k)) {
                var cnt1 = obj1[k] || 0;
                var cnt2 = obj2[k] || 0;
                var cnt = Math.abs(cnt1 - cnt2);
                for (var m = 0; m < cnt; m++) {
                    diff_arr.push(parseInt(k));
                }
                delete obj1[k];
                delete obj2[k];
            }
        }
        for (var k1 in obj1) {
            if (obj1.hasOwnProperty(k1)) {
                for (var obj1_idx = 0; obj1_idx < obj1[k1]; obj1_idx++) {
                    diff_arr.push(parseInt(k1));
                }
            }
        }
        for (var k2 in obj2) {
            if (obj2.hasOwnProperty(k2)) {
                for (var obj2_idx = 0; obj2_idx < obj2[k2]; obj2_idx++) {
                    diff_arr.push(parseInt(k2));
                }
            }
        }
        return diff_arr;
    },
    /**
     * 检测手牌
     * @param trun
     * @param cards
     * @returns {boolean}
     */
    checkHandCards: function (trun, cards) {
        if (trun != gameData.uid || (cards && cards.length == 0)) {
            return false;
        }
        var HandCard = deepCopy(this.SeverCardList);
        HandCard.sort(function (a, b) {
            return a - b;
        });
        cards.sort(function (a, b) {
            return a - b;
        });
        var result = !Equals(HandCard, cards);
        if (result) {
            showAlert('客户端牌不对了，result：' + result + "\n" + JSON.stringify(cards) + "\n" + JSON.stringify(HandCard));
        }
        return result
    },
    /**
     * 到谁出牌了，开始读秒
     * code 110
     * @param data
     */
    onTurnOut: function (data) {
        this.debuglog('onTurnOut');
        this.debuglog(data);
        this.Freeze = data['Freeze'];
        this.Notice = data['Notice'];
        this.Second = data['Second'];
        this.TurnOutSeq = data['Seq'];
        this.Turn = data['Turn'];
        if (data['HandCards'] && data['HandCards']['Cards'] && data['HandCards']['Cards'].length > 0) {
            this.checkHandCards(this.Turn, data['HandCards']['Cards']);
        }
        eventManager.dispatchEvent(ZiPaiEvent.TurnOut);
    },
    setChiArray: function () {
        if (this.ChiList == null || this.ChiList == undefined) {
            this.ChiArray = null;
            return;
        }
        this.ChiArray = [];
        for (var i = 0; i < this.ChiList['Nodes'].length; i++) {
            var chionei = [];
            if (this.ChiList['Nodes'][i]['Cards'].length > 0) {
                for (var j = 0; j < this.ChiList['Nodes'][i]['Cards'].length; j++) {
                    chionei.push(this.ChiList['Nodes'][i]['Cards'][j]);
                }
            }
            if (this.ChiList['Nodes'][i]['Nodes'].length > 0) {
                var chionex = [];
                for (var j = 0; j < this.ChiList['Nodes'][i]['Nodes'].length; j++) {
                    var chionej = [];
                    for (var l = 0; l < this.ChiList['Nodes'][i]['Nodes'][j]['Cards'].length; l++) {
                        chionej.push(this.ChiList['Nodes'][i]['Nodes'][j]['Cards'][l]);
                    }
                    //
                    if (this.ChiList['Nodes'][i]['Nodes'][j]['Nodes'].length > 0) {
                        var chioney = [];
                        for (var k = 0; k < this.ChiList['Nodes'][i]['Nodes'][j]['Nodes'].length; k++) {
                            var chionek = this.ChiList['Nodes'][i]['Nodes'][j]['Nodes'][k]['Cards'];
                            chioney.push(chionek);
                        }
                        chionej.push(chioney);
                    }
                    chionex.push(chionej);
                }
                chionei.push(chionex);
            }
            this.ChiArray.push(chionei);
        }
    },
    getChiArray: function () {
        return this.ChiArray;
    },
    /**
     * 请客户端选择是否进牌
     * code 111
     * @param data
     */
    onTurnIn: function (data) {
        this.debuglog('onTurnIn');
        this.debuglog(data);
        this.AcCards = data['AcCards'];
        this.TurnInCard = data['Card'];
        this.TurnInSeq = data['Seq'];
        this.ChiList = data['ChiList'];
        this.Flag = data['Flag'];
        this.Remark = data['Remark'];
        this.setChiArray();
        cc.log('Flag==' + this.Flag.toString(16));
        eventManager.dispatchEvent(ZiPaiEvent.TurnIn);
    },
    /**
     * 广播
     * code 112
     * @param data
     */
    onBroadCast: function (data) {
        this.debuglog('onBroadCast');
        this.debuglog(data);
        var action = data.Action;
        var actList = action.split('/');
        var userId = actList[0];
        var userPos = this.g_uid_to_pos[userId];
        this.BroadCastData = {
            action: action,
            actList: actList,
            userId: userId,
            actStatus: actList[1],
            actName: actList[2],
            card: parseInt(actList[3]),
            seq: parseInt(actList[4]),
            info: actList.length > 5 ? actList[5] : '',
            ScoreChange: data.ScoreChange,
            userPos: userPos,
            ismyself: (userPos == 0)
        };
        eventManager.dispatchEvent(ZiPaiEvent.BroadCast);
    },
    /**
     * 解散投票广播
     * code 116
     * @param data
     */
    onGameVote: function (data) {
        this.debuglog('onGameVote');
        this.debuglog(data);
        if (!data['Voting']) {
            return;
        }
        var byUserId = data['ByUserID'];
        if (byUserId == 0) {
            return;
        }
        var leftSeconds = data['EndSecond'];
        var voteResult = data['VoteResult'];
        leftSeconds = (leftSeconds < 0 ? 0 : leftSeconds);
        var RoomQuitWindow = window.curScene.getChildByName('RoomQuitWindow');
        if (!RoomQuitWindow) {
            RoomQuitWindow = showWindow('RoomQuitWindow', leftSeconds, data['Users'], byUserId, data);
        } else {
            RoomQuitWindow.setData(leftSeconds, data['Users'], byUserId, data);
            RoomQuitWindow.setVisible(true);
        }

        var acceptCount = 0;
        var arr_len = -1;
        var arr = data['Users'];
        if (arr) {
            for (var i = 0; i < arr.length; i++) {
                if (arr[i] && arr[i]['VoteValue'] == 1) {
                    acceptCount = acceptCount + 1;
                }
            }
            arr_len = arr.length;
        }
        this.isjiesanSucess = (acceptCount == arr_len);
    },
    /**
     * 跑马灯
     * code 117
     * @param data
     */
    onMaDeng: function (data) {
        this.debuglog('onMaDeng');
        this.debuglog(data);
    },
    /**
     * 房间结算
     * code 118
     * @param data
     */
    onRoomResult: function (data) {
        this.debuglog('onRoomResult');
        this.debuglog(data);
        this.RoomResultDate = data;
        if (this.isjiesanSucess) {
            eventManager.dispatchEvent(ZiPaiEvent.RoomResult);
        }
    },
    /**
     * 号被顶
     * code 119
     * @param data
     */
    onUserKick: function (data) {
        this.debuglog('onUserKick');
        this.debuglog(data);
    },
    /**
     * 广播每个人抓鸟，大鸟状态
     * code 120
     * @param data
     */
    onNiaoStatus: function (data) {
        this.debuglog('onNiaoStatus');
        this.debuglog(data);
        // IsSet: 0
        // IsZhuaNiao: 0
        // TuoNiao: 0
        // UserID: 1455499
        var Users = data['Users'];
    },
    /**
     * 请客户端断开连接，关闭定时器，重连等
     * code 121
     * @param data
     */
    onPlsDisconnect: function (data) {
        this.debuglog('onPlsDisconnect');
        this.debuglog(data);
        //network.disconnect();
    },
    /**
     * 广播玩家的举手状态，在每一轮开始的时候广播
     * code 122
     * @param data
     */
    onJushouStatus: function (data) {
        this.debuglog('onJushouStatus');
        this.debuglog(data);
        this.JushouStatus = data['Users'];
        eventManager.dispatchEvent(ZiPaiEvent.JushouStatus);
        // Users: Array(2)
        // 0: e {UserID: 1455499, IsSet: 0, CanSet: 0}
        // 1: e {UserID: 1404034, IsSet: 0, CanSet: 0}
        // length: 2
    },
    /**
     * 广播玩家的报警状态
     * code 123
     * @param data
     */
    onBaojing: function (data) {
        this.debuglog('onBaojing');
        this.debuglog(data);
        this.BaojingData = data['Users'];
        eventManager.dispatchEvent(ZiPaiEvent.Baojing);
    },
    /**
     * 广播玩家的翻醒状态
     * code 124
     * @param data
     */
    onFanXing: function (data) {
        this.debuglog('onFanXing');
        this.debuglog(data);
    },
    /**
     * 等待玩家选王调
     * code 125
     * @param data
     */
    onWangdiao: function (data) {
        this.debuglog('onWangdiao');
        this.debuglog(data);
    },
    /**
     * 手动准备
     * code 126
     * @param data
     */
    setPlayersStatus: function (data) {
        this.debuglog('setPlayersStatus');
        this.debuglog(data);
        var GameStatus = data['GameStatus'];
        var SecondStart = data['SecondStart'];
        var UserID = data['UserID'];
        var Users = data['Users'];
        this.SecondStart = SecondStart;
        this.GameStatus = GameStatus;
        this.PlayersStatus = Users;
        for (var i = 0; i < this.PlayersStatus.length; i++) {
            var ReadyData = this.PlayersStatus[i];
            var uid = ReadyData.UserID;
            if (uid == gameData.uid) {
                this.isShowReadyBtn = (!ReadyData['ReadyValue'] && GameStatus == 0);
                break;
            }
        }
        eventManager.dispatchEvent(ZiPaiEvent.PlayersStatus);
        if (this.GameStatus != 0) {
            eventManager.dispatchEvent(EventKey.ClubRoomStateChange, this.GameStatus);
        }
    },
    /**
     * * 网络连接断开
     * code 10001
     * @param data
     */
    NetWorkCloseFunc: function (data) {
        this.debuglog('NetWorkCloseFunc');
        this.debuglog(data);
    },
    /**
     * 切牌
     * code 128
     * @param data
     */
    onQiepai: function (data) {
        this.debuglog('onQiepai');
        this.debuglog(data);
        this.isGameStart = true;
        eventManager.dispatchEvent(ZiPaiEvent.QiePai, data);
    },
    /**
     * 快速开始
     * code 129
     * @param data
     */
    onQuickStart: function (data) {
        this.debuglog('onQuickStart');
        this.debuglog(data);
        if (!this.QuickStartWindow) {
            this.QuickStartWindow = showWindow('ZiPai_QuickStartWindow', data);
        } else {
            this.QuickStartWindow.setData(data);
        }
        this.QuickStartWindow.setVisible(data['ByWho'] != gameData.uid);
    },
    /**
     * code 130
     * @param data
     */
    onQuickStartGame: function (data) {
        this.debuglog('onQuickStartGame');
        this.debuglog(data);
        if (this.QuickStartWindow) {
            this.QuickStartWindow.removeFromParent(true);
            this.QuickStartWindow = null;
        }
        network.stop();
        if (data['Value'] == 1) {
            this.Option = JSON.parse(data['OldOption']);
            this.setOption();
            this.setUpPlayerPos(true);
            this.setZiPaiRoomData();
            this.isGameStart = true;
            eventManager.dispatchEvent(ZiPaiEvent.QuickStart);
            eventManager.dispatchEvent(EventKey.ClubRoomPlayerStateRefresh);
            eventManager.dispatchEvent(EventKey.ClubPlayerEnterExit, gameData.players);
            network.start();
        } else {
            showToast(data['Reason']);
            network.start();
        }
    },
    chuPai: function (card, outSeq) {
        network.sendPhz(5000, 'ShowCard/' + card + '/' + outSeq);
    },
});